#ifndef AER_EVENTHANDLER_HPP_
#define AER_EVENTHANDLER_HPP_

#include "../aerDefs.hpp"

#include <algorithm>
#include <set>
#include <SFML/Window.hpp>

/*
#if   (AER_USED_WM == AER_SFML)
# include  "SFML/aerEventHandler.hpp"
#elif (AER_USED_WM == AER_SDL)
# include  "SDL/aerEventHandler.hpp"
#else
# error     incorrect value for macro AER_USED_WM  !
#endif
*/


namespace aer {


/// ===========================================
/// Store per-frame events to be handled by the
/// application. [ uses SFML ]
/// ===========================================
class EventHandler
{
  public:
    friend class Application;
    
  private:
    typedef std::set<sf::Keyboard::Key> KeySet;
    typedef std::set<sf::Mouse::Button> MouseButtonSet;
    
    typedef KeySet::iterator          KeySetIterator;
    typedef MouseButtonSet::iterator MouseButtonIterator;
    
    struct MouseMotion
    {
      Vector2i prevPosition;
      Vector2i currPosition;
      Vector2  deltaPosition;
    };
    
    //
    struct JoystickMotion  {
      float position[4];
    };
    
  
  private:
    static sf::Event *sEvent;
    
    static KeySet          sKeyDown;
    static KeySet          sKeyToReleased;
    static MouseButtonSet sMouseButtonDown;
    static MouseButtonSet sMouseButtonToReleased;
    static MouseMotion    sMouse;
    static JoystickMotion sJoystick;
    static bool            sClosed;
    static bool            sResized;
    static bool            sGainedFocus;
    static bool            sLostFocus;
    static bool            sJoystickConnected;
    
    
  public:
    static bool IsKeyPressed(const sf::Keyboard::Key key);//
    static bool IsKeyReleased(const sf::Keyboard::Key key);//
    static bool IsKeyUp(const sf::Keyboard::Key key);//
    static bool IsKeyDown(const sf::Keyboard::Key key);//
    
    static bool IsMouseButtonPressed(const sf::Mouse::Button button);//
    static bool IsMouseButtonReleased(const sf::Mouse::Button button);//
    static bool IsMouseButtonUp(const sf::Mouse::Button button);//
    static bool IsMouseButtonDown(const sf::Mouse::Button button);//
    
    static const Vector2i& GetMousePosition() { return sMouse.currPosition; }
    static const Vector2&  GetMouseDelta()    { return sMouse.deltaPosition; }
    
    static const float GetJoystickAxisPosition(int axis) { return sJoystick.position[axis]; }
    
    static bool HasClosed()       { return sClosed; }
    static bool HasResized()      { return sResized; }
    static bool HasGainedFocus()  { return sGainedFocus; }
    static bool HasLostFocus()    { return sLostFocus; }
    static bool IsJoystickConnected() { return sJoystickConnected; }
    
  private:
    static void Begin(sf::Event *pEvent);
    static void End();
    
    static void HandleClose();
    static void HandleResize();
    static void HandleFocus(bool bGainFocus);
    static void HandleKeyboard(bool bKeyPressed);
    static void HandleMouseButton(bool bButtonPressed);
    static void HandleMouseMoved();
    //static void HandleWheelMoved();
    //static void HandleMouseFocus(bool bGainFocus);
    //static void HandleJoystickButton(bool bButtonDown);
    static void HandleJoystickMoved();
    static void HandleJoystickConnected(bool state);//
      
  private:
    DISALLOW_COPY_AND_ASSIGN(EventHandler);
};

} // aer

#endif //AER_EVENTHANDLER_HPP_
